home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Snippets
/
LaunchCreator 1.1
/
alias_to_fname.cc
next >
Wrap
C/C++ Source or Header
|
1996-06-08
|
6KB
|
137 lines
/*
*------------------------------------------------------------------------
When handling odoc (Open Document), pdoc (Print Document) and
similar AppleEvents, one sometimes needs to know the full directory
path to the document being opened. The "standard" way of going about
this is to obtain FSSpec from the AppleEvent record (or by coercing an
AliasRecord), and use FSSpec's parent directory id to walk up the
folder hierarchy (by repeatedly calling PBGetCatInfoSync())
reconstructing the full path. It works just fine, but kind of tedious:
filling out CInfoPBRec struct is rather messy. Recently I stumbled
upon an easier and shorter way, for a programmer. It's based on two
tricks:
- AliasRecord gotten from AEDescList of an odoc event record
is a minimal AliasRecord. We need the full record.
- It's very easy to get volume, folder, file names from the
full AliasRecord. No PBGetCatInfoSync() calls, at least, not by a
programmer.
Again, this technique (code below) would not probably save
too many instructions a CPU has to execute; but it'll definitely help bump
a few lines off the source code. One can also use these tricks to obtain
the full file path from any other AppleEvent pertaining to file(s), or
any AliasRecord or FSSpec for that matter.
Converting a minimal alias (say, "pointed" to by an 'alias_handle') to
the full one is a matter of four lines of code:
FSSpec resolved_target;
Boolean was_changed;
do_well( ResolveAlias(0,alias_handle,&resolved_target,&was_changed) );
do_well( UpdateAlias(0,&resolved_target,alias_handle,&was_changed) );
The code below defines a function to do the trick, as well as a test
driver to make sure the thing really works.
The code has been compiled and tested with CodeWarrior 5-7.
*------------------------------------------------------------------------
*/
#define RUN_TEST 0
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// Execute a function 'ex' and make sure
// it returns noErr
#define do_well(ex) \
{ OSErr err = (ex); if( err != noErr ) \
fprintf(stderr,"Failed call " #ex " with error %ld at line %ld of `%s'.", \
err, __LINE__, __FILE__), exit(4); }
// Get a full path from an alias record
// Returns a pointer to a static string
// Note, alias has to be a full alias
// (minimal alias doesn't have directories record)
const char * get_full_path(AliasHandle alias_handle)
{
static char path[700]; // Full path to return
Str63 buffer;
// Write a volume name at the beginning of
// the path
do_well( GetAliasInfo(alias_handle,asiVolumeName,buffer) );
memcpy(path,(char *)buffer+1,buffer[0]);
char * first_col_pos = path + buffer[0];
*first_col_pos = ':'; // colon after the volume name
char * after_ldir_pos = first_col_pos+1;
// Put directory names from the parent upwards
// In the string
// Volume_name:Dir3:Dir2:Dir1:
// first_col_pos points to the first : after
// the volume name, after_ldir_pos points
// after the last column. The new directory
// retrieved from the alias record is wedged
// between the volume name and first_col_pos
for(register int dir_level=1;;dir_level++)
{
do_well( GetAliasInfo(alias_handle,dir_level,buffer) );
if( buffer[0] == 0 )
break; // no more (grand...dad) directories
// Move [after_vname_pos,after_ldir_pos)
// chunk forward to make room for this
// (grand)parent directory
char * p = after_ldir_pos;
char * q = after_ldir_pos += buffer[0]+1; // reserve space for :
assert( after_ldir_pos < path + sizeof(path) );
while( p > first_col_pos )
*--q = *--p;
p = (char *)buffer+1+buffer[0]; // End of the (grand)parent dir name
while( q > first_col_pos+1 )
*--q = *--p;
}
// Get the file name itself and append it to the
// end
do_well( GetAliasInfo(alias_handle,asiAliasName,buffer) );
assert( after_ldir_pos+buffer[0]+1 < path + sizeof(path) );
memcpy(after_ldir_pos,(char *)buffer+1,buffer[0]);
after_ldir_pos[buffer[0]] = '\0'; // Properly terminate the string
return path;
}
#if defined(RUN_TEST) && RUN_TEST
// Test driver
// Since getting an AppleEvent and taking
// an AliasRecord from it is a bit of a hassle
// we use a simpler test: convert a full file
// name into an alias record, and get it back
void main(void)
{
FSSpec file_spec;
do_well(FSMakeFSSpec(0,0,"\pA System:SYSTEM FOLDER:HOSTS",&file_spec));
AliasHandle alias; // Pretend this alias is from an AppleEvent
do_well( NewAliasMinimal(&file_spec,&alias) );
// Now do our trick of turning a min alias to a
// full one (see comments above). Of course we could've
// made the full alias right upfront above. But in
// real applications, an alias from an odoc/pdoc/etc
// AppleEvent is a min one, and we don't get any choice
{
FSSpec resolved_target;
Boolean was_changed;
do_well( ResolveAlias(0,alias,&resolved_target,&was_changed) );
do_well( UpdateAlias(0,&resolved_target,alias,&was_changed) );
}
printf("\nThe full file name obtained from an alias is '%s'\n",
get_full_path(alias));
DisposHandle((Handle)alias);
}
#endif